<template>
	<jk-dialog
		v-model="showDialog"
		:title="`${dataId ? '编辑' : '新增'}-菜单`"
		:show-content-loading="showLoading"
		width="800px"
		:confirm-btn-loading="confirmBtnLoading"
		append-to-body
		@on-visible-change="onVisibleChange"
		@on-confirm="onConfirmBtn"
		@on-cancel="onVisibleChange(false)"
	>
		<el-form ref="ruleForm" :model="ruleForm" size="medium" :rules="rules" :show-message="false" label-width="120px">
			<el-row>
				<el-col :span="24">
					<el-form-item class="margin-bottom-10" label="上级菜单" prop="menuPathIds">
						<el-cascader
							ref="tree"
							v-model="ruleForm.menuPathIds"
							:options="menuList"
							class="width-100-percent"
							placeholder="上级菜单"
							:props="{
								value: 'id',
								label: 'name',
								checkStrictly: true
							}"
						></el-cascader>
					</el-form-item>
				</el-col>
				<el-col :span="24">
					<el-form-item class="margin-bottom-10" label="菜单类型" prop="type">
						<el-radio-group v-model="ruleForm.type" @change="onTypeRatioChange">
							<el-radio v-for="item in menuTypeList" :key="item.id" class="margin-right-10" border :label="item.id">{{ item.name }}</el-radio>
						</el-radio-group>
					</el-form-item>
				</el-col>
				<el-col :span="24">
					<el-form-item v-if="ruleForm.type !== 3" class="margin-bottom-10" label="菜单图标">
						<el-popover placement="bottom-start" width="530" trigger="click" @show="$refs['iconSelect'].reset()">
							<icon-select ref="iconSelect" @selected="onSelectChange" />
							<el-tag slot="reference" size="large" type="primary" style="font-size: 20px; cursor: pointer;">
								<div v-if="ruleForm.icon">
									<i :class="ruleForm.icon"></i>
								</div>
							</el-tag>
						</el-popover>
					</el-form-item>
				</el-col>
				<el-col :span="12">
					<el-form-item class="margin-bottom-10" label="菜单名称" prop="name">
						<el-input v-model.trim="ruleForm.name" placeholder="请输入菜单名称" />
					</el-form-item>
				</el-col>
				<el-col :span="12">
					<el-form-item class="margin-bottom-10" label="显示排序" prop="sort">
						<el-input-number v-model="ruleForm.sort" controls-position="right" class="width-100-percent" :min="0" />
					</el-form-item>
				</el-col>
				<el-col :span="12">
					<el-form-item v-if="ruleForm.type !== 3" class="margin-bottom-10" label="路由地址" prop="path">
						<span slot="label">
							<el-tooltip content="访问的路由地址，如：`user`。如需外网地址时，则以 `http(s)://` 开头" placement="top">
								<i class="el-icon-question"></i>
							</el-tooltip>
							路由地址
						</span>
						<el-input v-model.trim="ruleForm.path" placeholder="请输入路由地址" />
					</el-form-item>
				</el-col>
				<!--<el-col v-if="ruleForm.type === 2" :span="12">
					<el-form-item class="margin-bottom-10" label="组件路径" prop="component">
						<el-input v-model.trim="ruleForm.component" placeholder="请输入组件路径" />
					</el-form-item>
				</el-col>-->
				<el-col v-if="ruleForm.type === 2" :span="12">
					<el-form-item class="margin-bottom-10" label="分类" prop="component">
						<jk-select v-model="ruleForm.categoryId" :option-list="categoryList" class="width-100-percent" size="medium" placeholder="分类" />
					</el-form-item>
				</el-col>

				<el-col :span="12">
					<el-form-item v-if="ruleForm.type !== 1" class="margin-bottom-10" label="权限标识">
						<span slot="label">
							<el-tooltip content="Controller 方法上的权限字符，如：@PreAuthorize(`@ss.hasPermission('system:user:list')`)" placement="top">
								<i class="el-icon-question"></i>
							</el-tooltip>
							权限字符
						</span>
						<el-input v-model="ruleForm.permission" placeholder="请权限标识" maxlength="50" />
					</el-form-item>
				</el-col>
				<el-col :span="12">
					<el-form-item class="margin-bottom-10" label="菜单状态" prop="status">
						<span slot="label">
							<el-tooltip content="选择停用时，路由将不会出现在侧边栏，也不能被访问" placement="top">
								<i class="el-icon-question"></i>
							</el-tooltip>
							菜单状态
						</span>
						<el-radio-group v-model="ruleForm.status">
							<el-radio-button v-for="item in statusList" :key="item.id" :label="item.id">{{ item.name }}</el-radio-button>
						</el-radio-group>
					</el-form-item>
				</el-col>
				<el-col :span="12">
					<el-form-item v-if="ruleForm.type !== 3" class="margin-bottom-10" label="显示状态">
						<span slot="label">
							<el-tooltip content="选择隐藏时，路由将不会出现在侧边栏，但仍然可以访问" placement="top">
								<i class="el-icon-question"></i>
							</el-tooltip>
							是否显示
						</span>
						<el-radio-group v-model="ruleForm.visible">
							<el-radio :key="true" :label="true">显示</el-radio>
							<el-radio :key="false" :label="false">隐藏</el-radio>
						</el-radio-group>
					</el-form-item>
				</el-col>
				<el-col :span="12">
					<el-form-item v-if="ruleForm.type === 2" class="margin-bottom-10" label="显示状态">
						<span slot="label">
							<el-tooltip content="选择缓存时，则会被 `keep-alive` 缓存，需要匹配组件的 `name` 和路由地址保持一致" placement="top">
								<i class="el-icon-question"></i>
							</el-tooltip>
							是否缓存
						</span>
						<el-radio-group v-model="ruleForm.keepAlive">
							<el-radio :key="true" :label="true">缓存</el-radio>
							<el-radio :key="false" :label="false">不缓存</el-radio>
						</el-radio-group>
					</el-form-item>
				</el-col>
			</el-row>
		</el-form>
	</jk-dialog>

</template>

<script>
    import { systemMenuDetail, systemMenuCreate, systemMenuList, systemMenuUpdate } from '../../../api/system/menu';
    import calDialogHeight from '../../../mixins/cal-dialog-height';
    import iconSelect from '../../../components/IconSelect';
    import { isExternal } from '../../../utils/validate';
    import { menuCategoryList, statusList } from '../../../utils/jk/status-option-list';
    import { createTree, getFamily } from '../../../utils/jk/jk-tool';
    import { validateArr } from '../../../utils/jk/validator';
    export default {
        mixins: [calDialogHeight],
        components: { iconSelect },
        props: {
            dialogState: {
                type: Boolean,
                default: false
            },
            title: {
                type: String,
                default: ''
            },
            dataId: {
                type: [String, Number],
                default: ''
            },
            isAdd: {
                type: Boolean,
                default: false
            }
        },
        data() {
            return {
                categoryList: menuCategoryList,
                statusList: statusList,
                menuTypeList: [
                    { id: 1, name: '目录' },
                    { id: 2, name: '菜单' },
                    { id: 3, name: '按钮' }
                ],
                showLoading: false,
                confirmBtnLoading: false,
                ruleForm: {
                    menuPathIds: [],
                    parentId: null,
                    name: '',
                    type: 1,
                    icon: 'el-icon-zoom-in',
                    status: 1,
                    visible: true,
                    keepAlive: false,
                    permission: '',
                    component: '',
                    path: '',
                    sort: 1,
                    remark: ''
                },
                rules: {
                    menuPathIds: [{ required: true, validator: validateArr, trigger: 'change' }],
                    type: [{ required: true, trigger: 'change' }],
                    name: [{ required: true, trigger: 'change' }]
                },
                menuList: [],
                showDialog: false,
                originalData: []
            };
        },
        methods: {
            onTypeRatioChange() {
                this.$set(this.ruleForm, 'categoryId', null);
            },
            // 选择图标
            onSelectChange(name) {
                this.$set(this.ruleForm, 'icon', name);
            },
            getMenuListRequest() {
                return systemMenuList({
                    types: [1, 2]
                }).then(res => {
                    if (res.data.status === 200) {
                        const resData = [
                            { id: 0, name: '根路径', parentId: null },
                            ...JSON.parse(JSON.stringify(res.data.res))
                        ];
                        this.originalData = JSON.parse(JSON.stringify(resData));
                        this.menuList = [];
                        this.menuList = createTree(resData, {});
                    }
                });
            },
            getDetailRequest() {
                return systemMenuDetail(this.dataId).then(res => {
                    if (res.data.status === 200) {
                        this.ruleForm = res.data.res;
                        this.$set(this.ruleForm, 'menuPathIds', getFamily(this.originalData, res.data.res.parentId).ids);
                        this.$nextTick(() => {
                            if (res.data.res.menuIds) {
                                this.$refs.menu.setCheckedKeys(res.data.res.menuIds);
                            }
                        });
                    }
                });
            },
            onConfirmBtn() {
                this.$refs['ruleForm'].validate(valid => {
                    if (valid) {
                        this.$set(this.ruleForm, 'parentId', this.ruleForm.menuPathIds[this.ruleForm.menuPathIds.length - 1]);
                        // 若权限类型为目录或者菜单时，进行 path 的校验，避免后续拼接出来的路由无法跳转
                        if (this.ruleForm.type === 1 || this.ruleForm.type === 2) {
                            // 如果是外链，则不进行校验
                            const path = this.ruleForm.path;
                            if (!isExternal(path)) {
                                // 父权限为根节点，path 必须以 / 开头
                                if (this.ruleForm.parentId === 0 && path.charAt(0) !== '/') {
                                    this.$modal.msgSuccess('路由路径必须以 / 开头');
                                    return;
                                } else if (this.ruleForm.parentId !== 0 && path.charAt(0) === '/') {
                                    this.$modal.msgSuccess('路由路径不能以 / 开头');
                                    return;
                                }
                            }
                        }

                        this.saveRequest().then(res => {
                            this.confirmBtnLoading = false;
                            if (res.data.status === 200) {
                                this.$tipsBar(this, 'save');
                                this.$emit('on-finish');
                            }
                        });
                    }
                });
            },
            saveRequest() {
                this.confirmBtnLoading = true;
                const categoryItem = this.categoryList.find(x => x.id === this.ruleForm.categoryId) || {};
                this.$set(this.ruleForm, 'categoryName', categoryItem.name);
                // 新增
                if (this.isAdd) {
                    this.$set(this.ruleForm, 'id', null);
                    return systemMenuCreate(this.ruleForm);
                } else {
                    // 编辑
                    return systemMenuUpdate(this.ruleForm);
                }
            },
            async getDependentData() {
                this.showLoading = true;
                await this.getMenuListRequest();
                if (!this.isAdd && this.dataId) await this.getDetailRequest();
                if (this.isAdd) {
                    this.$set(this.ruleForm, 'parentId', this.dataId);
                    this.$set(this.ruleForm, 'menuPathIds', getFamily(this.originalData, this.dataId).ids);
                }
                this.showLoading = false;
            },
            onVisibleChange(e) {
                this.$emit('on-visible-change', e);
                if (!e) {
                    Object.assign(this.$data.ruleForm, this.$options.data().ruleForm);
                    this.$nextTick(() => {
                        this.$refs.ruleForm.resetFields();
                    });
                }
            }
        },
        watch: {
            dialogState(newVal) {
                this.showDialog = newVal;
                if (newVal) {
                    this.getDependentData();
                }
            }
        }
    };
</script>
